#include "config_app_field_def_parser.h"
#include <fstream>
#include <iostream>

#include "json/json.h"
#include "log.h"
#include "comm_enum.h"

std::map<std::string, int> FieldTypeMap::field_type_map_;
VET_INDEX_NAMESPACE_BEGIN

#define FIELD_VECTOR 15

bool AppFieldContext::ParseConfig()
{
    const std::string s_path_const = "../conf/app_field_define.json";

    std::ifstream i_stream(s_path_const.c_str());
    if (!i_stream.is_open()) {
        log_error("load %s failed.", s_path_const.c_str());
        return false;
    }

    FieldTypeMap::Init();
    Json::Reader reader;
    Json::Value o_table_define;
    if (reader.parse(i_stream, o_table_define)
        && o_table_define.isMember("tableDefine")){
        Json::Value o_table_define_cont = o_table_define["tableDefine"];
        if (o_table_define_cont.isArray()) {
            for (int i = 0; i < (int)o_table_define_cont.size(); ++i) {
                AppidType ui_appid = 0;
                if (o_table_define_cont[i].isMember("appId")
                    && o_table_define_cont[i]["appId"].isUInt()){
                    ui_appid = o_table_define_cont[i]["appId"].asUInt();
                }else{
                    log_error("appId is incorrect");
                    return false;
                }

                if (o_table_define_cont[i].isMember("fieldDefine") && o_table_define_cont[i]["fieldDefine"].isArray()){
                    Json::Value o_field_define_cont = o_table_define_cont[i]["fieldDefine"];
                    for (int i = 0; i < (int)o_field_define_cont.size(); ++i){
                        uint32_t ui_fieldtype = 0;
                        if (o_field_define_cont[i].isMember("fieldType")
                            && o_field_define_cont[i]["fieldType"].isUInt()){
                            ui_fieldtype = o_field_define_cont[i]["fieldType"].asUInt();
                        }else if(o_field_define_cont[i].isMember("fieldType")
                            && o_field_define_cont[i]["fieldType"].isString()){
                            ui_fieldtype = FieldTypeMap::GetIntType(o_field_define_cont[i]["fieldType"].asString());
                        }else{
                            log_error("fieldType is incorrect");
                            return false;
                        }
                        if (ui_fieldtype != FIELD_VECTOR) {
                            continue;
                        }


                        FieldIdType ui_field_id;
                        if (o_field_define_cont[i].isMember("fieldId")
                            && o_field_define_cont[i]["fieldId"].isUInt()){
                            ui_field_id = o_field_define_cont[i]["fieldId"].asUInt();
                        }else{
                            log_error("fieldId is incorrect");
                            return false;
                        }

                        VectorIndexCont o_vector_index_cont;
                        if (o_field_define_cont[i].isMember("dim")
                            && o_field_define_cont[i]["dim"].isUInt()){
                            o_vector_index_cont.ui_dim_ = o_field_define_cont[i]["dim"].asUInt();
                            if (0 == o_vector_index_cont.ui_dim_) {
                                log_error("dim should not be zero");
                                return false;
                            }
                        }else{
                            log_error("dim is incorrect");
                            return false;
                        }

                        if (o_field_define_cont[i].isMember("indexType")
                            && o_field_define_cont[i]["indexType"].isArray()){
                                Json::Value o_index_type_array = o_field_define_cont[i]["indexType"];
                                for (int i_type = 0;
                                    i_type < (int)o_index_type_array.size(); ++i_type) {
                                        if (o_index_type_array[i_type].isString()) {
                                            o_vector_index_cont.index_type_str_array_.push_back(
                                                o_index_type_array[i_type].asString()
                                            );
                                        }
                                }
                        }else{
                            log_error("indexType is incorrect");
                            return false;
                        }

                        if (o_field_define_cont[i].isMember("indexDir")
                            && o_field_define_cont[i]["indexDir"].isArray()){
                                Json::Value o_index_dir_array = o_field_define_cont[i]["indexDir"];
                                for (int i_type = 0;
                                    i_type < (int)o_index_dir_array.size(); ++i_type) {
                                        if (o_index_dir_array[i_type].isString()) {
                                            o_vector_index_cont.index_dir_array_.push_back(
                                                o_index_dir_array[i_type].asString()
                                            );
                                        }
                                }
                        } else {
                            log_error("indexDir is incorrect");
                            return false;
                        }

                        if (o_field_define_cont[i].isMember("searchIndexType")
                            && o_field_define_cont[i]["searchIndexType"].isUInt()){
                            o_vector_index_cont.ui_search_index_type_ = 
                                o_field_define_cont[i]["searchIndexType"].asUInt();
                        }else{
                            log_error("searchIndexType is incorrect");
                            return false;
                        }

                        if (o_field_define_cont[i].isMember("metricType")
                            && o_field_define_cont[i]["metricType"].isString()){
                            o_vector_index_cont.s_metric_type_ = 
                                o_field_define_cont[i]["metricType"].asString();
                        }else{
                            log_error("metricType is incorrect");
                            return false;
                        }

                        if (!o_vector_index_cont.IsValid()) {
                            log_error("search index type is surpass the index upper limit");
                            return false;
                        }
                        
                        o_app_field_table_[ui_appid][ui_field_id] = o_vector_index_cont;
                    }
                }
            }
        }else{
            log_error("tableDefine is incorrect");
            return false;
        }
    } else {
        log_error("config file: %s has error format" , s_path_const.c_str());
        i_stream.close();
        return false;
    }
    return true;
}

bool AppFieldContext::ValidityCheck(
    AppidType ui_appid ,
    FieldIdType ui_field_id)
{
    if (o_app_field_table_.find(ui_appid) != o_app_field_table_.end()) {
        if (o_app_field_table_[ui_appid].find(ui_field_id) 
        != o_app_field_table_[ui_appid].end()) {
            return true;
        } 
    } 
    return false;
}

VET_INDEX_NAMESPACE_END